context 是個處理流程中關於『超時限制』的控制器
lib context
https://pkg.go.dev/context@go1.17.3
常用的 context 方法
WithCancel: cancellation
WithDeadline and WithTimeout: deadline/timeout and cancellation
WithValue: key-value pairs
來看看幾個例子
ctx, cancel := context.WithCancel(context.Background())
time.AfterFunc(4*time.Second, func() {
cancel()
})
go func() {
<-ctx.Done()
fmt.Println("Context done!")
}()
go func() {
time.Sleep(1 * time.Second)
fmt.Println("After 1 second:", ctx.Err())
}()
go func() {
time.Sleep(3 * time.Second)
fmt.Println("After 3 seconds:", ctx.Err())
}()
go func() {
time.Sleep(5 * time.Second)
fmt.Println("After 5 seconds:", ctx.Err())
}()
time.Sleep(6 * time.Second)
上述例子中,會在第四秒時發出 cancel() 訊號
輸出為
After 1 second: <nil>
After 3 seconds: <nil>
Context done!
After 5 seconds: context canceled
第五秒時 本 context 已 cancel
第二個例子
ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
_ = cancel // 本例中不使用 cancel
go func() {
<-ctx.Done()
fmt.Println("Context done!")
}()
go func() {
time.Sleep(1 * time.Second)
fmt.Println("After 1 second:", ctx.Err())
}()
go func() {
time.Sleep(3 * time.Second)
fmt.Println("After 3 seconds:", ctx.Err())
}()
go func() {
time.Sleep(5 * time.Second)
fmt.Println("After 5 seconds:", ctx.Err())
}()
time.Sleep(6 * time.Second)
上述例子中,使用 WithTimeout 設定本 context 會在第四秒時超時
輸出為
After 1 second: <nil>
After 3 seconds: <nil>
Context done!
After 5 seconds: context deadline exceeded
第三個例子
ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second)
time.AfterFunc(2*time.Second, func() {
cancel()
})
go func() {
<-ctx.Done()
fmt.Println("Context done!")
}()
go func() {
time.Sleep(1 * time.Second)
fmt.Println("After 1 second:", ctx.Err())
}()
go func() {
time.Sleep(3 * time.Second)
fmt.Println("After 3 seconds:", ctx.Err())
}()
go func() {
time.Sleep(5 * time.Second)
fmt.Println("After 5 seconds:", ctx.Err())
}()
time.Sleep(6 * time.Second)
同時使用 WithTimeout & cancel()
context 在 cancel 後就不會 time out 了
輸出為
After 1 second: <nil>
Context done!
After 3 seconds: context canceled
After 5 seconds: context canceled
context 可以確保處理流程的安全性(thread-safe),更準確的是指 goroutine-safe
context 是不可變動的,只能基於現有的 context 創出新的 子 context